/**
 * Copyright (C) 2010 - 2013 Harry Glasgow
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.jaden.ui.dialog;

import com.googlecode.jaden.common.config.ProjectConfiguration;
import com.googlecode.jaden.common.other.JadenException;
import com.googlecode.jaden.common.other.Utils;
import com.googlecode.jaden.ui.UiUtils;
import com.googlecode.jaden.ui.UI;
import static com.googlecode.jaden.ui.Constants.*;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Set;
import java.util.TreeSet;
import java.util.prefs.Preferences;

public class EditFileMappingsDialog extends BaseDialog {

    private final UI ui;
    private final SpinnerNumberModel outputColumnSpinnerModel;
    private final SpinnerNumberModel inputColumnSpinnerModel;
    private final JComboBox<String> inputsCombo;
    private final int[] inputMappings;
    private final JSpinner inputColumnSpinner;
    private boolean adjusting;

    public EditFileMappingsDialog(UI ui, Preferences preferences, ProjectConfiguration project) {
        super(ui, DIALOG_FILE_MAPPINGS_TITLE);
        this.ui = ui;
        outputColumnSpinnerModel = new SpinnerNumberModel(1, 1, 999, 1);
        JSpinner outputColumnSpinner = new JSpinner(outputColumnSpinnerModel);
        DefaultComboBoxModel<String> inputsComboModel = new DefaultComboBoxModel<String>();
        inputsCombo = new JComboBox<String>(inputsComboModel);
        inputColumnSpinnerModel = new SpinnerNumberModel(1, 1, 999, 1);
        inputColumnSpinner = new JSpinner(inputColumnSpinnerModel);
        inputColumnSpinner.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                updateInputColumn();
            }
        });

        JLabel inputColumnsLabel = new JLabel(Utils.translate(LABEL_INPUT_COLUMNS_TEXT));
        JLabel inputFileColumnLabel = new JLabel(Utils.translate(LABEL_INPUT_FILE_COLUMN_TEXT));
        JLabel outputFileColumnLabel = new JLabel(Utils.translate(LABEL_OUTPUT_FILE_COLUMN_TEXT));

        UiUtils.enWidth(inputFileColumnLabel, outputFileColumnLabel);

        JPanel mainPanel = UiUtils.verticalList(
                UiUtils.horizontalList(inputColumnsLabel, inputsCombo),
                UiUtils.horizontalList(inputFileColumnLabel, inputColumnSpinner),
                new JSeparator(SwingConstants.HORIZONTAL),
                UiUtils.horizontalList(outputFileColumnLabel, outputColumnSpinner));
        setMainPanel(mainPanel, preferences);

        int numberOfInputs = project.getInputConfigurations().length;
        for (int i = 0; i < numberOfInputs; i++) {
            inputsComboModel.addElement(project.getInputConfigurations()[i].getName());
        }
        outputColumnSpinnerModel.setValue(project.getOutputColumnMapping() + 1);
        inputMappings = new int[project.getInputColumnMappings().length];
        int i = 0;
        for (int mapping : project.getInputColumnMappings()) {
            inputMappings[i++] = mapping + 1; // Human readable
        }

        inputsCombo.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                updateInputColumnSpinner();
            }
        });

        updateInputColumnSpinner();
    }

    private void updateInputColumnSpinner() {
        int index = inputsCombo.getSelectedIndex();
        if (index == -1) {
            inputColumnSpinner.setEnabled(false);
        } else {
            inputColumnSpinner.setEnabled(true);
            adjusting = true;
            inputColumnSpinnerModel.setValue(inputMappings[index]);
            adjusting = false;
        }
    }

    protected void doOk() throws JadenException {

        Set<Integer> set = new TreeSet<Integer>();
        for (int mapping : inputMappings) {
            set.add(mapping);
        }
        set.add(outputColumnSpinnerModel.getNumber().intValue());
        if (set.size() != inputMappings.length + 1) {
            throw new JadenException(Utils.translate(ERROR_BAD_IO_COLUMN_MAPPINGS));
        }
        // Convert from human readable.
        int[] translatedInputMappings = new int[inputMappings.length];
        for (int i = 0; i < inputMappings.length; i++) {
            translatedInputMappings[i] = inputMappings[i] - 1;
        }
        ui.updateMappings(translatedInputMappings,
                outputColumnSpinnerModel.getNumber().intValue() - 1);
        dispose();
    }

    private void updateInputColumn() {
        if (!adjusting) {
            int index = inputsCombo.getSelectedIndex();
            inputMappings[index] = inputColumnSpinnerModel.getNumber().intValue();
        }
    }

}